import { unref } from 'vue';
import type { App, Component, Plugin } from 'vue';

import { cloneDeep, isObject } from 'lodash-es';

/** 递归组装菜单格式 */
export function generatorMenu(routerMap: Array<any>) {
  return filterRouter(routerMap).map((item) => {
    const isRoot = isRootRouter(item);
    const info = isRoot ? item.children[0] : item;
    const currentMenu = {
      ...info,
      ...info.meta,
      label: info.meta?.title,
      key: info.name,
      icon: isRoot ? item.meta?.icon : info.meta?.icon,
    };
    // 是否有子菜单，并递归处理
    if (info.children && info.children.length > 0) {
      // Recursion
      currentMenu.children = generatorMenu(info.children);
    }
    return currentMenu;
  });
}

/** 混合菜单 */
export function generatorMenuMix(
  routerMap: Array<any>,
  routerName: string,
  location: string,
) {
  const cloneRouterMap = cloneDeep(routerMap);
  const newRouter = filterRouter(cloneRouterMap);
  if (location === 'header') {
    const firstRouter: any[] = [];
    newRouter.forEach((item) => {
      const isRoot = isRootRouter(item);
      const info = isRoot ? item.children[0] : item;
      info.children = undefined;
      const currentMenu = {
        ...info,
        ...info.meta,
        label: info.meta?.title,
        key: info.name,
      };
      firstRouter.push(currentMenu);
    });
    return firstRouter;
  }
  return getChildrenRouter(
    newRouter.filter((item) => item.name === routerName),
  );
}

/** 递归组装子菜单 */
export function getChildrenRouter(routerMap: Array<any>) {
  return filterRouter(routerMap).map((item) => {
    const isRoot = isRootRouter(item);
    const info = isRoot ? item.children[0] : item;
    const currentMenu = {
      ...info,
      ...info.meta,
      label: info.meta?.title,
      key: info.name,
    };
    // 是否有子菜单，并递归处理
    if (info.children && info.children.length > 0) {
      // Recursion
      currentMenu.children = getChildrenRouter(info.children);
    }
    return currentMenu;
  });
}

/** 判断根路由 Router */
export function isRootRouter(item) {
  return (
    item.meta?.alwaysShow != true &&
    item?.children?.filter((item) => !item?.meta?.hidden)?.length === 1
  );
}

export const withInstall = <T extends Component>(
  component: T,
  alias?: string,
) => {
  const comp = component as any;
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component);
    if (alias) {
      app.config.globalProperties[alias] = component;
    }
  };
  return component as Plugin & T;
};

/** 找到对应的节点 */
let result = null;
export function getTreeItem(data: any[], key?: number | string): any {
  data.map((item) => {
    if (item.key === key) {
      result = item;
    } else if (item.children && item.children.length > 0) {
      getTreeItem(item.children, key);
    }
  });
  return result;
}

/** 找到所有节点 */
const treeAll: any[] = [];
export function getTreeAll(data: any[]): any[] {
  data.map((item) => {
    treeAll.push(item.key);
    if (item.children && item.children.length > 0) {
      getTreeAll(item.children);
    }
  });
  return treeAll;
}

// dynamic use hook props
export function getDynamicProps<T extends {}, U>(props: T): Partial<U> {
  const ret: Recordable = {};

  Object.keys(props).map((key) => {
    ret[key] = unref((props as Recordable)[key]);
  });

  return ret as Partial<U>;
}

export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
  let key: string;
  for (key in target) {
    src[key] = isObject(src[key])
      ? deepMerge(src[key], target[key])
      : (src[key] = target[key]);
  }
  return src;
}

/**
 * Sums the passed percentage to the R, G or B of a HEX color
 *
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed part of the color
 */
function addLight(color: string, amount: number) {
  const cc = Number.parseInt(color, 16) + amount;
  const c = cc > 255 ? 255 : cc;
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
}

/**
 * Lightens a 6 char HEX color according to the passed percentage
 *
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed color represented as HEX
 */
export function lighten(color: string, amount: number) {
  color = color.includes('#') ? color.substring(1, color.length) : color;
  amount = Math.trunc((255 * amount) / 100);
  return `#${addLight(color.slice(0, 2), amount)}${addLight(
    color.slice(2, 4),
    amount,
  )}${addLight(color.slice(4, 6), amount)}`;
}

/** 判断是否 url */
export function isUrl(url: string) {
  return /^(http|https):\/\//.test(url);
}

/**
 * 数组结构转树形结构
 *
 * @param {Array} arrayData 数据源
 * @param {object} treeProps 树结构配置 { id:"_id", parent_id:"parent_id",
 *   children:"children",need_field:["_id","name"],deleteParentId:true }
 * @returns {Array} treeData 树形结构
 */
export function arrayToTree(originalArrayData, treeProps) {
  const arrayData = cloneDeep(originalArrayData);
  let {
    id = '_id',
    parent_id = 'parent_id',
    children = 'children',
    deleteParentId = false,
    need_field,
  } = treeProps;
  const result = [];
  const temp = {};
  for (const arrayDatum of arrayData) {
    temp[arrayDatum[id]] = arrayDatum; // 以id作为索引存储元素，可以无需遍历直接定位元素
  }
  for (const currentElement of arrayData) {
    const newCurrentElement = {};
    if (need_field) {
      need_field = uniqueArr([...need_field, id, parent_id, children]);
      for (const keyName in currentElement) {
        if (!need_field.includes(keyName)) {
          delete currentElement[keyName];
        }
      }
    }
    const tempCurrentElementParent = temp[currentElement[parent_id]]; // 临时变量里面的当前元素的父元素
    if (tempCurrentElementParent) {
      // 如果存在父元素
      if (!tempCurrentElementParent[children]) {
        // 如果父元素没有chindren键
        tempCurrentElementParent[children] = []; // 设上父元素的children键
      }
      if (deleteParentId) {
        delete currentElement[parent_id];
      }
      tempCurrentElementParent[children].push(currentElement); // 给父元素加上当前元素作为子元素
    } else {
      // 不存在父元素，意味着当前元素是一级元素
      result.push(currentElement);
    }
  }
  return result;
}

// 最简单数组去重法
export function uniqueArr(array) {
  const n = []; // 一个新的临时数组
  // 遍历当前数组
  for (const element of array) {
    // 如果当前数组的第i已经保存进了临时数组，那么跳过，
    // 否则把当前项push到临时数组里面
    if (!n.includes(element)) n.push(element);
  }
  return n;
}

// 大写下划线格式对象转成小写驼峰
export function convertKeysToCamelCase(obj) {
  const result = {};
  Object.keys(obj).forEach((key) => {
    // 判断键是否为大写下划线格式
    if (/^[A-Z]+(_[A-Z]+)*$/.test(key)) {
      // 将大写下划线格式转换为小写驼峰格式
      const camelCaseKey = key
        .split('_')
        .map((part, index) => {
          if (index === 0) {
            return part.toLowerCase();
          }
          return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
        })
        .join('');
      result[camelCaseKey] = obj[key];
    } else {
      result[key] = obj[key];
    }
  });
  return result;
}
